import { ErrorHandler } from './api.js'

// 错误类型枚举
export const ErrorType = {
  NETWORK: 'network',
  API: 'api',
  VALIDATION: 'validation',
  AUTHENTICATION: 'authentication',
  AUTHORIZATION: 'authorization',
  BUSINESS: 'business',
  UNKNOWN: 'unknown'
}

// 统一错误处理类
export class UnifiedErrorHandler {
  static instance = null
  
  constructor() {
    this.errorListeners = []
    this.messageHandler = null
    this.setupGlobalErrorHandling()
  }
  
  static getInstance() {
    if (!UnifiedErrorHandler.instance) {
      UnifiedErrorHandler.instance = new UnifiedErrorHandler()
    }
    return UnifiedErrorHandler.instance
  }
  
  // 设置消息处理器（集成UI组件）
  setMessageHandler(handler) {
    this.messageHandler = handler
  }
  
  // 添加错误监听器
  addErrorListener(listener) {
    this.errorListeners.push(listener)
  }
  
  // 移除错误监听器
  removeErrorListener(listener) {
    this.errorListeners = this.errorListeners.filter(l => l !== listener)
  }
  
  // 设置全局错误处理
  setupGlobalErrorHandling() {
    // 处理未捕获的Promise错误
    window.addEventListener('unhandledrejection', (event) => {
      console.error('Unhandled promise rejection:', event.reason)
      this.handleError(event.reason, 'Global Promise Rejection')
      event.preventDefault()
    })
    
    // 处理JavaScript错误
    window.addEventListener('error', (event) => {
      console.error('Global JavaScript error:', event.error)
      this.handleError(event.error, 'Global JavaScript Error')
    })
  }
  
  // 主要错误处理方法
  handleError(error, context = '', options = {}) {
    const {
      showNotification = true,
      logError = true,
      redirectOnAuth = true
    } = options
    
    // 解析错误信息
    const errorInfo = this.parseError(error, context)
    
    // 记录错误
    if (logError) {
      this.logError(errorInfo)
    }
    
    // 通知所有监听器
    this.notifyListeners(errorInfo)
    
    // 特殊处理认证错误
    if (errorInfo.type === ErrorType.AUTHENTICATION && redirectOnAuth) {
      this.handleAuthenticationError()
      return errorInfo
    }
    
    // 显示用户通知
    if (showNotification) {
      this.showUserNotification(errorInfo)
    }
    
    return errorInfo
  }
  
  // 解析错误信息
  parseError(error, context) {
    let type = ErrorType.UNKNOWN
    let message = '发生未知错误'
    let code = null
    let details = null
    
    if (error) {
      // API错误
      if (error.code) {
        type = this.getErrorTypeByCode(error.code)
        code = error.code
        message = error.message || this.getDefaultMessageByType(type)
        details = error.details
      }
      // 网络错误
      else if (error.request && !error.response) {
        type = ErrorType.NETWORK
        message = '网络连接异常，请检查网络设置'
      }
      // HTTP错误
      else if (error.response) {
        const status = error.response.status
        type = this.getErrorTypeByStatus(status)
        message = error.message || this.getDefaultMessageByStatus(status)
        details = error.response.data
      }
      // 普通JavaScript错误
      else if (error instanceof Error) {
        message = error.message
        type = ErrorType.UNKNOWN
      }
      // 字符串错误
      else if (typeof error === 'string') {
        message = error
      }
    }
    
    return {
      type,
      message,
      code,
      details,
      context,
      timestamp: new Date().toISOString(),
      originalError: error
    }
  }
  
  // 根据错误代码获取错误类型
  getErrorTypeByCode(code) {
    const codeTypeMap = {
      'INVALID_CREDENTIALS': ErrorType.AUTHENTICATION,
      'AUTHENTICATION_FAILED': ErrorType.AUTHENTICATION,
      'AUTHORIZATION_FAILED': ErrorType.AUTHORIZATION,
      'VALIDATION_ERROR': ErrorType.VALIDATION,
      'RESOURCE_NOT_FOUND': ErrorType.API,
      'DATA_NOT_FOUND': ErrorType.BUSINESS,
      'PREDICTION_FAILED': ErrorType.BUSINESS,
      'INTERNAL_SERVER_ERROR': ErrorType.API
    }
    
    return codeTypeMap[code] || ErrorType.UNKNOWN
  }
  
  // 根据HTTP状态码获取错误类型
  getErrorTypeByStatus(status) {
    if (status === 401) return ErrorType.AUTHENTICATION
    if (status === 403) return ErrorType.AUTHORIZATION
    if (status === 404) return ErrorType.API
    if (status >= 400 && status < 500) return ErrorType.VALIDATION
    if (status >= 500) return ErrorType.API
    return ErrorType.UNKNOWN
  }
  
  // 根据错误类型获取默认消息
  getDefaultMessageByType(type) {
    const typeMessageMap = {
      [ErrorType.NETWORK]: '网络连接异常',
      [ErrorType.API]: 'API调用失败',
      [ErrorType.VALIDATION]: '请求参数错误',
      [ErrorType.AUTHENTICATION]: '认证失败',
      [ErrorType.AUTHORIZATION]: '权限不足',
      [ErrorType.BUSINESS]: '业务处理失败',
      [ErrorType.UNKNOWN]: '发生未知错误'
    }
    
    return typeMessageMap[type] || '发生未知错误'
  }
  
  // 根据HTTP状态码获取默认消息
  getDefaultMessageByStatus(status) {
    const statusMessageMap = {
      400: '请求参数错误',
      401: '认证失败，请重新登录',
      403: '权限不足',
      404: '请求的资源不存在',
      422: '请求参数验证失败',
      500: '服务器内部错误',
      502: '网关错误',
      503: '服务暂时不可用'
    }
    
    return statusMessageMap[status] || `请求失败 (${status})`
  }
  
  // 处理认证错误
  handleAuthenticationError() {
    // 清除本地存储
    localStorage.removeItem('access_token')
    localStorage.removeItem('user_info')
    
    // 跳转到登录页
    if (window.location.pathname !== '/login') {
      window.location.href = '/login'
    }
  }
  
  // 显示用户通知
  showUserNotification(errorInfo) {
    if (this.messageHandler) {
      // 使用自定义消息处理器
      this.messageHandler(errorInfo)
    } else {
      // 使用浏览器默认通知
      console.error('Error:', errorInfo.message)
      
      // 尝试使用页面上的通知组件
      if (typeof window !== 'undefined') {
        // iView Message组件
        if (window.Vue && window.Vue.prototype.$Message) {
          window.Vue.prototype.$Message.error(errorInfo.message)
        }
        // Element UI Message组件
        else if (window.Vue && window.Vue.prototype.$message) {
          window.Vue.prototype.$message.error(errorInfo.message)
        }
        // 最后使用alert
        else {
          alert(errorInfo.message)
        }
      }
    }
  }
  
  // 记录错误
  logError(errorInfo) {
    const logData = {
      timestamp: errorInfo.timestamp,
      type: errorInfo.type,
      message: errorInfo.message,
      code: errorInfo.code,
      context: errorInfo.context,
      details: errorInfo.details,
      userAgent: navigator.userAgent,
      url: window.location.href
    }
    
    console.error('[Error Log]', logData)
    
    // 这里可以集成错误日志服务
    // 例如：Sentry, LogRocket, 或自定义日志API
  }
  
  // 通知所有监听器
  notifyListeners(errorInfo) {
    this.errorListeners.forEach(listener => {
      try {
        listener(errorInfo)
      } catch (error) {
        console.error('Error in error listener:', error)
      }
    })
  }
}

// 创建单例实例
export const errorHandler = UnifiedErrorHandler.getInstance()

// Vue插件
export const ErrorHandlerPlugin = {
  install(Vue, options = {}) {
    // 设置消息处理器
    if (options.messageHandler) {
      errorHandler.setMessageHandler(options.messageHandler)
    } else if (Vue.prototype.$Message) {
      // 默认使用iView Message
      errorHandler.setMessageHandler((errorInfo) => {
        Vue.prototype.$Message.error(errorInfo.message)
      })
    }
    
    // 添加到Vue原型
    Vue.prototype.$errorHandler = errorHandler
    
    // 全局错误处理
    Vue.config.errorHandler = (error, vm, info) => {
      console.error('Vue error:', error, 'Component:', vm, 'Info:', info)
      errorHandler.handleError(error, `Vue Component: ${info}`)
    }
    
    // 添加全局方法
    Vue.prototype.$handleError = (error, context, options) => {
      return errorHandler.handleError(error, context, options)
    }
  }
}

// 工具函数
export const createAsyncErrorHandler = (context) => {
  return async (asyncFn, ...args) => {
    try {
      return await asyncFn(...args)
    } catch (error) {
      errorHandler.handleError(error, context)
      throw error
    }
  }
}

// 装饰器函数（用于async/await）
export const withErrorHandling = (context, options = {}) => {
  return (target, propertyKey, descriptor) => {
    const originalMethod = descriptor.value
    
    descriptor.value = async function(...args) {
      try {
        return await originalMethod.apply(this, args)
      } catch (error) {
        errorHandler.handleError(error, `${target.constructor.name}.${propertyKey}`, options)
        if (!options.suppressError) {
          throw error
        }
      }
    }
    
    return descriptor
  }
}

export default errorHandler 